package cn.imvc.app.models;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.hibernate.StaleObjectStateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.opensearch.CloudsearchSearch;
import com.puff.cache.redis.Redis;

import cn.imvc.app.domains.GoodsQueryBean;
import cn.imvc.app.domains.GoodsState;
import cn.imvc.app.domains.PageDomain;
import cn.imvc.app.entities.AttrValue;
import cn.imvc.app.entities.Brand;
import cn.imvc.app.entities.BrandGoodsClass;
import cn.imvc.app.entities.Goods;
import cn.imvc.app.entities.GoodsClass;
import cn.imvc.app.entities.GoodsClassAttr;
import cn.imvc.app.entities.PriceClass;
import cn.imvc.app.entities.TypeValue;
import cn.imvc.app.repositories.AttrValueRepository;
import cn.imvc.app.repositories.BrandGoodsClassRepository;
import cn.imvc.app.repositories.GoodsClassAttrRepository;
import cn.imvc.app.repositories.GoodsClassRepository;
import cn.imvc.app.repositories.GoodsRepository;
import cn.imvc.app.repositories.PriceClassRepository;
import cn.imvc.core.ICache;
import cn.imvc.util.GoodsSearch;
import cn.imvc.util.PageableUtils;
import cn.imvc.util.ToolUtils;

@Service
public class GoodsModelImpl implements GoodsModel {
	@Autowired
	private GoodsRepository goodsRepository;
	@Autowired
	private PriceClassRepository priceClassRepository;
	@Autowired
	private GoodsClassRepository goodsClassRepository;
	@Autowired
	private BrandGoodsClassRepository brandGoodsClassRepository;
	@Autowired
	private GoodsClassAttrRepository goodsClassAttrRepository;
	@Autowired
	private AttrValueRepository attrValueRepository;
	@Autowired
	private CommonModel commonModel;
	@Autowired
	private TypeValueModel typeValueModel;
	@Autowired
	private BrandModel brandModel;
	@Autowired
	private ApplicationContext applicationContext;
	@Autowired
	ICache cache;
	@Autowired
	GoodsSearch goodsSearch;

	@Value("${goods.defaultPriceClassCode}")
	private String defaultPriceClassCode;

	public Page<Goods> findByBrandId(Integer brandId, Integer page, String sort) {
		Page<Goods> pageResult = null;
		String key = "goodsListByBrand" + brandId + "_" + page + "_" + sort;
		int minute = ToolUtils.getMinute(new Date());
		PageDomain<Goods> domain = null;
		// cache.remove("DATA", key);
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					PageRequest pageRequest = PageableUtils.bulidPageRequest(page, PAGE_SIZE, sort, true);
					pageResult = goodsRepository.findByBrandIdAndState(brandId, (byte) 1, pageRequest);
					domain = new PageDomain<Goods>();
					domain.setPage(pageResult);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getPage();
			}
		}
		return pageResult;
	}

	public Page<Goods> findByGoodsClassId(Integer goodsClassId, Integer page, String sort) {
		Page<Goods> pageResult = null;
		String key = "goodsListByClass" + goodsClassId + "_" + page + "_" + sort;
		int minute = ToolUtils.getMinute(new Date());
		PageDomain<Goods> domain = null;
		// cache.remove("DATA", key);
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					PageRequest pageRequest = PageableUtils.bulidPageRequest(page, PAGE_SIZE, sort, true);
					pageResult = goodsRepository.findByGoodsClassIdAndState(goodsClassId, (byte) 1, pageRequest);
					domain = new PageDomain<Goods>();
					domain.setPage(pageResult);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getPage();
			}
		}
		return pageResult;
	}

	public Goods findById(Integer id) {
		return goodsRepository.findOne(id);
	}

	public Page<Object[]> findPageResult(Integer goodsClassId, Integer page, String sort) {
		if (goodsClassId == null || goodsClassId == 0) {
			return findAllPageResult(page, sort);
		}
		// cache.removeSecond("MAX_ID", "goodsClass");
		Integer goodsClassMaxId = commonModel.findMaxId("goodsClass");

		if (goodsClassId > goodsClassMaxId) {
			return null;
		}
		String key = "goodsListByClass" + goodsClassId + "_" + page + "_" + sort;
		int minute = ToolUtils.getMinute(new Date());
		PageDomain<Object[]> domain = null;
		// cache.remove("DATA", key);
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					PageRequest pageRequest = PageableUtils.bulidPageRequest(page, PAGE_SIZE, sort, true);
					String sql = "select g.id,g.image, g.name, gp.price,g.salenum,g.evaluationCount from goods g,goods_price gp  where g.id = gp.goodsId and g.goodsClassId= ?1 and gp.priceClassId= ?2 group BY g.id ";
					PriceClass priceClass = priceClassRepository.findByCode(defaultPriceClassCode);
					Assert.notNull(priceClass);
					Page<Object[]> pageResult = goodsRepository.findPageResultBySql(sql, new Object[] { goodsClassId, priceClass.getId() }, pageRequest);
					domain = new PageDomain<Object[]>();
					domain.setPage(pageResult);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					return pageResult;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getPage();
			}
		}
	}

	/**
	 * 拼接sql
	 * 
	 * @param goodsClassId
	 * @param showPriceClassId
	 * @param sortStr
	 */
	private String bulidSql(Integer goodsClassId, Integer showPriceClassId, String sortStr) {
		StringBuffer sb = new StringBuffer(
				"select g.id,g.image, g.name, gp.price,g.salenum,g.evaluationCount from goods g,goods_price gp  where g.id = gp.goodsId and g.goodsClassId= "
						+ goodsClassId + " and gp.priceClassId=" + showPriceClassId + " group BY g.id ");
		sb.append("order by ");
		if (sortStr != null && !"".equals(sortStr.trim())) {
			String[] sorts = sortStr.split(",");
			for (String order : sorts) {
				sb.append(order.split("_")[0]).append(" ").append(order.split("_")[1]);
			}
		} else {
			sb.append("g.id desc");
		}
		return sb.toString();
	}

	public Goods get(int id) {
		return goodsRepository.findOne(id);
	}

	public Goods save(Goods goods) {

		Goods goods2 = goodsRepository.saveAndFlush(goods);

		return goods2;
	}

	public void delete(int id) {
		goodsRepository.delete(id);

	}

	public void retrySaveGoods(Integer goodsId, Integer click, Integer salenum, Integer collect, Integer evaluationCount) {
		Goods goods = get(goodsId);
		try {
			goods.setClick((goods.getClick() == null ? 0 : goods.getClick()) + click);
			goods.setSalenum((goods.getSalenum() == null ? 0 : goods.getSalenum()) + salenum);
			goods.setCollect((goods.getCollect() == null ? 0 : goods.getCollect()) + collect);
			goods.setEvaluationCount((goods.getEvaluationCount() == null ? 0 : goods.getEvaluationCount()) + evaluationCount);
			save(goods);
		} catch (StaleObjectStateException e) {
			applicationContext.getBean(GoodsModel.class).retrySaveGoods(goodsId, click, salenum, collect, evaluationCount);
		}
	}

	public List<Object[]> findMaxId() {
		return goodsRepository.findAllSql("select max(id) from goods");
	}

	public Page<Object[]> findAllPageResult(Integer page, String sort) {
		String key = "goodsListByClassAll_" + page + "_" + sort;
		int minute = ToolUtils.getMinute(new Date());
		PageDomain<Object[]> domain = null;
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					PriceClass priceClass = priceClassRepository.findByCode(defaultPriceClassCode);
					Assert.notNull(priceClass);
					PageRequest pageRequest = PageableUtils.bulidPageRequest(page, PAGE_SIZE, sort, true);
					String sql = "select g.id,g.image, g.name, gp.price,g.salenum,g.evaluationCount from goods g,goods_price gp  where g.id = gp.goodsId and gp.priceClassId= ?1 group BY g.id ";
					Page<Object[]> pageResult = goodsRepository.findPageResultBySql(sql, new Object[] { priceClass.getId() }, pageRequest);
					domain = new PageDomain<Object[]>();
					domain.setPage(pageResult);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					return pageResult;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getPage();
			}
		}
	}

	public Map<String, Object> getSearchFilters(Integer goodsClassId) {
		String key = "searchFilters" + goodsClassId;
		int minute = ToolUtils.getMinute(new Date());
		PageDomain<Object> domain = null;
		Map<String, Object> result = new HashMap<String, Object>();
		// cache.remove("DATA", key);
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					domain = new PageDomain<Object>();
					List<GoodsClass> goodsClassList = null;
					List<BrandGoodsClass> brandGoodsClassList = null;
					List<GoodsClassAttr> goodsClassAttrList = null;
					Map<String, List<AttrValue>> attrValueMap = new HashMap<String, List<AttrValue>>();
					if (goodsClassId != null && goodsClassId > 0) {// 有一级分类
						GoodsClass goodsClass = goodsClassRepository.findOne(goodsClassId);
						result.put("goodsClassName", goodsClass.getName());
						if (goodsClass.getParent() == null) {
							goodsClassList = goodsClassRepository.findByParentId(goodsClassId);
						} else {// 如果是二级分类
							goodsClassList = goodsClassRepository.findByParentId(goodsClass.getParent().getId());
						}
						brandGoodsClassList = brandGoodsClassRepository.findByGoodsClassId(goodsClassId);
						goodsClassAttrList = goodsClassAttrRepository.findByGoodsClassId(goodsClassId);
					} else {// 显示一级分类
						goodsClassList = goodsClassRepository.findByParentIdIsNull();
						// 默认品牌
						brandGoodsClassList = brandGoodsClassRepository.findByGoodsClassIdIsNull();
						goodsClassAttrList = goodsClassAttrRepository.findByGoodsClassIdIsNull();
					}
					if (goodsClassAttrList != null) {
						int[] attrClassIds = goodsClassAttrList.stream().mapToInt(item -> item.getAttr() != null ? item.getAttr().getId() : 0).toArray();
						List<AttrValue> attrValueList = attrValueRepository.findByAttrClassIdInOrderBySort(attrClassIds);
						attrValueMap = attrValueList.stream().collect(Collectors.groupingBy(attrValue -> "attrClass" + attrValue.getAttrClass().getId()));
					}
					// 分类过滤
					result.put("goodsClassList", goodsClassList);
					result.put("brandGoodsClassList", brandGoodsClassList);
					result.put("goodsClassAttrList", goodsClassAttrList);
					result.put("attrValueMap", attrValueMap);
					domain.setMapResult(result);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				result = domain.getMapResult();
				break;
			}
		}

		return result;
	}

	public Page<Object[]> findPageResult(GoodsQueryBean goodsQueryBean) {
		// TODO 修改分页数
		PageRequest pageable = PageableUtils.bulidPageRequest(goodsQueryBean.getPage(), 2, goodsQueryBean.getSort(), true);
		Map<String, Object> sqlMap = getSqlByQueryBean(goodsQueryBean);
		String sql = (String) sqlMap.get("sql");
		List args = (List) sqlMap.get("args");
		Page<Object[]> result = goodsRepository.findPageResultBySql(sql, args.toArray(), pageable);
		return result;
	}

	private Map<String, Object> getSqlByQueryBean(GoodsQueryBean goodsQueryBean) {
		Map<String, Object> result = new HashMap<>();
		List<Object> args = new ArrayList<Object>();
		String keyword = goodsQueryBean.getKeyWord();
		Integer goodsClassId = goodsQueryBean.getGoodsClassId();
		List<String> attrValueIds = goodsQueryBean.getAttrIds();
		Integer brandId = goodsQueryBean.getBrandId();
		StringBuffer selectSql = new StringBuffer("select g.id,g.image, g.name, gp.price,g.salenum,g.evaluationCount ");
		StringBuffer fromSql = new StringBuffer(" from goods g,goods_price gp ");
		StringBuffer whereSql = new StringBuffer(" where g.id = gp.goodsId and gp.priceClassId= ?1 ");
		// StringBuffer orderSql = new StringBuffer(" order by ");
		StringBuffer groupSql = new StringBuffer(" group BY g.id");
		PriceClass priceClass = priceClassRepository.findByCode(defaultPriceClassCode);
		Assert.notNull(priceClass);
		args.add(priceClass.getId());
		int index = 2;
		if (attrValueIds != null && attrValueIds.size() > 0) {
			attrValueIds = attrValueIds.stream().filter(item -> item != null).collect(Collectors.toList());
			if (attrValueIds != null && attrValueIds.size() > 0) {

			}
		}
		if (!StringUtils.isEmpty(keyword)) {
			whereSql.append(" and g.name like ?" + (index++) + " ");
			args.add("%" + keyword + "%");
		}
		if (goodsClassId != null && goodsClassId > 0) {
			whereSql.append(
					" and (g.goodsClassId = ?" + (index++) + " or g.goodsClassId in (select id from goods_class where parentId = ?" + (index++) + " )) ");
			args.add(goodsClassId);
			args.add(goodsClassId);
		}
		if (brandId != null && brandId > 0) {
			whereSql.append(" and g.brandId = ?" + (index++) + " ");
			args.add(brandId);
		}
		String sql = selectSql.append(fromSql).append(whereSql).append(groupSql).toString();
		result.put("sql", sql);
		result.put("args", args);
		return result;
	}

	public List<Goods> findTopListOrderBySaleNum(Integer limitNum) {
		PageDomain<Goods> domain = null;
		String key = "hotsaleGoods" + limitNum;
		int minute = ToolUtils.getMinute(new Date());
		List<Goods> result = null;
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					result = goodsRepository.findTopListOrderBySaleNum((byte)GoodsState.NORMAL.getCode(),limitNum);
					domain = new PageDomain<Goods>();
					domain.setListResult(result);
					cache.put("DATA", key, domain, 1800);
					Redis.getInstance().remove(key + minute);
					break;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getListResult();
			}
		}
		return result;
	}

	public Page<Goods> cloudSearchGoods(GoodsQueryBean goodsQueryBean) {
		return getPagedCloudSearch(goodsQueryBean);
	}

	private Page<Goods> getPagedCloudSearch(GoodsQueryBean goodsQueryBean) {
		Page<Goods> result = null;
		String keywords = goodsQueryBean.getKeyWord();
		Integer page = goodsQueryBean.getPage();
		if (page == null) {
			page = 0;
		}
		Integer goodsClassId = goodsQueryBean.getGoodsClassId();
		Integer brandId = goodsQueryBean.getBrandId();
		// 格式 col1_orderType1,col2_orderType2,...
		String sortsStr = goodsQueryBean.getSort();
		List<String> attrValueIds = goodsQueryBean.getAttrIds();
		String typeClassStr = goodsQueryBean.getTypeClass();
		try {
			CloudsearchSearch search = goodsSearch.getSearch();
			search.setStartHit(page * GoodsModel.PC_PAGE_SIZE);
			search.setHits(GoodsModel.PC_PAGE_SIZE);
			if (brandId != null && brandId != 0) {
				search.addFilter("brandid=" + brandId);
			}
			// 状态为正常
			Integer goodsState = goodsQueryBean.getGoodsState();
			if(goodsState!=null&&goodsState!=0){
				search.addFilter("state="+goodsState);
			}else{
				search.addFilter("(state=1 OR state=3)");
			}
			
			// 状态为审核通过
			search.addFilter("verify=1");
			if (!StringUtils.isEmpty(sortsStr)) {
				String[] sorts = sortsStr.split(",");
				for (String sort : sorts) {
					String[] tem = sort.split("_");
					if (!StringUtils.isEmpty(tem) && tem.length == 2) {
						search.addSort(tem[0], "desc".equalsIgnoreCase(tem[1]) ? "-" : "+");
					}
				}
			}
			StringBuffer attrStr = new StringBuffer();
			if (attrValueIds != null && attrValueIds.size() > 0) {
				attrValueIds = attrValueIds.stream().filter(item -> item != null && !"".equals(item)).collect(Collectors.toList());
				if (attrValueIds != null && attrValueIds.size() > 0) {
					for (String attrValue : attrValueIds) {
						attrStr.append("" + attrValue + " ");
					}
				}
			}
			StringBuffer queryStr = new StringBuffer();
			boolean appendFlag = false;
			if (!StringUtils.isEmpty(keywords)) {
				queryStr.append("default:'" + keywords + "' ");
				appendFlag = true;
			}
			//
			if (goodsClassId != null && goodsClassId != 0) {
				//search.addFilter("goodsclassid=" + goodsClassId);
				if (appendFlag) {
					queryStr.append(" AND ");
				} else {
					appendFlag = true;
				}
				queryStr.append(" classstr:'" + goodsClassId + "' ");
			}
			if (!StringUtils.isEmpty(attrStr.toString())) {
				if (appendFlag) {
					queryStr.append(" AND ");
				} else {
					appendFlag = true;
				}
				queryStr.append(" attr:'" + attrStr.toString().trim() + "' ");
			}
			if (!StringUtils.isEmpty(typeClassStr)) {
				if (appendFlag) {
					queryStr.append(" AND ");
				} else {
					appendFlag = true;
				}
				queryStr.append(" typestr:'" + typeClassStr.toString().trim() + "' ");
			}
			search.setQueryString(queryStr.toString());
			try {
				String json = search.search();
				JSONObject jb = JSON.parseObject(json);
				result = parsePage(jb, page);
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		return result;
	}

	private Page<Goods> parsePage(JSONObject jb, Integer page) {
		// 状态 OK
		String status = jb.getString("status");
		JSONObject resultObject = jb.getJSONObject("result");
		JSONArray items = resultObject.getJSONArray("items");
		Long total = resultObject.getLong("total");
		PageRequest pageable = new PageRequest(page, GoodsModel.PC_PAGE_SIZE);
		List<Goods> goodsList = JSON.parseArray(items.toJSONString(), Goods.class);
		return new PageImpl<Goods>(goodsList, pageable, total);
	}

	public GoodsQueryBean getShowParams(GoodsQueryBean goodsQueryBean) {
		String typeValueId = goodsQueryBean.getTypeClass();
		Integer brandId = goodsQueryBean.getBrandId();
		if (typeValueId != null && typeValueId.matches("\\d+")) {
			TypeValue typeValue = typeValueModel.findOne(Integer.parseInt(typeValueId));
			goodsQueryBean.setTypeClassName(typeValue.getName());
		}
		if (brandId != null && brandId!=0) {
			Brand brand = brandModel.getBrand(brandId);
			if(brand!=null){
				goodsQueryBean.setBrandName(brand.getName());
			}
		}
		return goodsQueryBean;
	}

	public List<Goods> getRalationGoods(Integer goodsId) throws Exception {
		PageDomain<Goods> domain = null;
		String key = "ralationGoods" + goodsId;
		int minute = ToolUtils.getMinute(new Date());
		List<Goods> result = new ArrayList<Goods>();
		while (true) {
			domain = cache.get("DATA", key);
			if (domain == null) {
				if (Redis.getInstance().setnx(key + minute, "aa") == 1) {
					Redis.getInstance().expire(key + minute, 20);
					try {
						// 查找买过该商品的用户
						CloudsearchSearch search;
						search = goodsSearch.getGoodsOrder();
						Calendar c = Calendar.getInstance();
						c.setTime(new Date());
						c.add(Calendar.MONTH, -1);
						search.addFilter("createdat>" + c.getTime().getTime());
						search.addDistinct("memberid", 1, 1, "false");
						search.setHits(500);
						search.setQueryString("goodsid:'" + goodsId + "'");
						String json = null;
						json = search.search();
						JSONObject jb = JSON.parseObject(json);
						String status = jb.getString("status");
						if (!"OK".equals(status)) {
							return null;
						}
						JSONObject resultObject = jb.getJSONObject("result");
						JSONArray items = resultObject.getJSONArray("items");

						// 查询所有这些用户买的商品的数量
						search = goodsSearch.getGoodsOrder();
						List<Map<String, Object>> mapList = (List) items;
						for (Map<String, Object> map : mapList) {
							search.addFilter("memberid='" + map.get("memberid").toString() + "'", "OR");
						}
						search.setHits(0);
						search.addAggregate("goodsid", "count()");
						json = search.search();
						jb = JSON.parseObject(json);
						status = jb.getString("status");
						if (!"OK".equals(status)) {
							return null;
						}
						resultObject = jb.getJSONObject("result");
						JSONArray facet = resultObject.getJSONArray("facet");
						items = ((JSONObject) facet.get(0)).getJSONArray("items");
						mapList = (List) items;
						int[][] a = new int[mapList.size()][2];
						int s = 0;
						for (Map<String, Object> map : mapList) {
							if (Integer.parseInt(map.get("value").toString()) != goodsId) {
								s++;
								a[s][0] = Integer.parseInt(map.get("count").toString());
								a[s][1] = Integer.parseInt(map.get("value").toString());
							}
						}
						if (s > 5) {
							// 堆排序
							int[] tmp = new int[2];
							int adjust = 0;
							// 堆排序初始化
							for (int i = s / 2; i > 0; i--) {
								if (a[i * 2][0] <= a[i * 2 + 1][0]) {
									adjust = 1;
								} else {
									adjust = 0;
								}
								if (a[i][0] < a[i * 2 + adjust][0]) {
									tmp = a[i];
									a[i] = a[i * 2 + adjust];
									a[i * 2 + adjust] = tmp;
								}

							}
							// 堆排序排序
							for (int i = 0; i < 4; i++) {
								tmp = a[1];
								a[1] = a[s - i];
								a[s - i] = tmp;
								int now = 1;
								while (now * 2 < s - i) {
									if ((now * 2 + 1 < s - i) && (a[now * 2][0] <= a[now * 2 + 1][0])) {
										adjust = 1;
									} else {
										adjust = 0;
									}
									tmp = a[now];
									a[now] = a[now * 2 + adjust];
									a[now * 2 + adjust] = tmp;
									now = now * 2 + adjust;

								}
							}
						}
						result = new ArrayList<Goods>();
						for (int i = s; i > 0; i--) {
							if (s - i > 4) {
								break;
							}
							result.add(goodsRepository.findOne(a[i][1]));
						}
					} catch (Exception e) {
						Redis.getInstance().remove(key + minute);
						throw new Exception();
					}
					domain = new PageDomain<Goods>();
					domain.setListResult(result);
					cache.put("DATA", key, domain, 3600);
					Redis.getInstance().remove(key + minute);
					return result;
				} else {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} else {
				return domain.getListResult();
			}
		}
	}
}
